<?php
/*
 * Questo file definisce tre classi:
 * - AbstractFormatter
 * - XHTMLFormatter
 * - PDFFormatter
 */

abstract class AbstractFormatter
{
	protected $dom;
	protected $schema;

	protected $name;

	protected $layout;
	protected $skin;
	protected $layoutDir;
	protected $skinDir;
	protected $layoutExt;
	protected $skinExt;

	protected $xslDir;

	public function __construct ()
	{
		$this->dom = new DomDocument ("1.0","UTF-8");
		$this->xslDir = "../../data/ltw0807/df/xsl";
	}

	public function readXML ()
	{
		/*
		 * Controllo POST.
		 */
		if (!is_array ($_POST) || @$_POST[$this->name] == '') {
			echo DFError ("400", "Dati non inviati.");
			return false;
		}
		/*
		 * Caricamento XML nel DOM e validazione.
		 */
		$this->dom->loadXML (stripslashes ($_POST[$this->name]));
		if (!@$this->dom->schemaValidate ($this->schema)) {
			echo DFError ("400", "Inviato XML non valido.");
			return false;
		}
		 

		/*
		 * Recupera gli id di layout e skin.
		 */
		$this->layout = $this->dom->getElementsByTagName("layout")->item(0)->getAttribute("id");
		$skinNodeList = $this->dom->getElementsByTagName("skin");
		if ($skinNodeList->length != 0)
			$this->skin = $skinNodeList->item(0)->getAttribute("id");

		if (!$this->layoutAndSkinExist())
		      	return false;

		return true;
	}

	protected abstract function layoutAndSkinExist ();

	public abstract function transform ();
}


abstract class XHTMLFormatter extends AbstractFormatter
{
	protected $xp;
	protected $xsl;

	public function __construct ()
	{
		parent::__construct ();

		global $DF_URI;
		$htmldir = "html{$DF_URI}";

		$this->name = "piadina";
		$this->layoutDir = "../../{$htmldir}/xhtml/css";
		$this->skinDir = "../../{$htmldir}/xhtml/css";
		$this->layoutExt = "css";
		$this->skinExt = "css";
		$this->xslDir = "{$this->xslDir}/xhtml";

		$this->xsl = new DomDocument ("1.0","UTF-8");
		$this->xp = new XsltProcessor ();
		$this->xsl->load ("{$this->xslDir}/main-nutella.xsl");
	}

	/*
	 * Il codice XHTML generato e' uno solo, quindi tutti i CSS sono 
	 * compatibili e basta controllare che esistano i file del layout e 
	 * e della skin.
	 */
	protected function layoutAndSkinExist ()
	{
		if (!file_exists ("{$this->layoutDir}/{$this->layout}.{$this->layoutExt}")) {
			echo DFError ("404", "Layout {$this->layout} inesistente.");
			return false;
		}

		if ($this->skin != ""
		    && !file_exists ("{$this->skinDir}/{$this->skin}.{$this->skinExt}")) {
			echo DFError ("404", "Skin {$this->skin} inesistente.");
			return false;
		}

		return true;
	}

	public function transform ()
	{
		global $HOST;
		global $DF_URI;

		$this->xp->setParameter ('', "layout-url", "http://{$HOST}{$DF_URI}/xhtml/css/{$this->layout}.{$this->layoutExt}");
		$this->xp->setParameter ('', "skin-url", "http://{$HOST}{$DF_URI}/xhtml/css/{$this->skin}.{$this->skinExt}");

		$this->xp->importStylesheet ($this->xsl);

		if ($html = $this->xp->transformToXML($this->dom)) {
			output_typed_string($html, "application/xhtml+xml");
			return true;
		}
		echo DFError ("500", "Formattazione non riuscita.");
		return false;
	}
}


class XHTMLFragmentFormatter extends XHTMLFormatter
{
	public function __construct ()
	{
		parent::__construct ();

		$this->schema = "http://vitali.web.cs.unibo.it/twiki/pub/TechWeb08/SCHEMA/formatta_frammento.xsd";
	}

	public function transform ()
	{
		$this->xp->setParameter ('', "type", "fragment");
		parent::transform();
	}
}


class XHTMLDocumentFormatter extends XHTMLFormatter
{
	public function __construct ()
	{
		parent::__construct ();

		$this->schema = "http://vitali.web.cs.unibo.it/twiki/pub/TechWeb08/SCHEMA/formatta_documento.xsd";
	}

	public function transform ()
	{
		$this->xp->setParameter ('', "type", "document");
		parent::transform();
	}
}


class PDFDocumentFormatter extends AbstractFormatter
{
	protected $tempDir;
	protected $pdfDir;
	protected $foFile;

	public function __construct ()
	{
		global $BASE_URI,$DF_URI;

		parent::__construct ();

		$this->name = "tigella";
		$this->layoutDir = "../../data/ltw0807/df/xsl/pdf";
		$this->skinDir = "../../data/ltw0807/df/xsl/pdf";
		$this->layoutExt = "xsl";
		$this->skinExt = "xsl";
		$this->xslDir=$this->xslDir."/pdf/";

		$this->schema = "http://vitali.web.cs.unibo.it/twiki/pub/TechWeb08/SCHEMA/formatta_documento.xsd";

		$this->tempDir = "../../data/ltw0807/df/temp/";
		$this->pdfDir = "../../html{$DF_URI}/pdf/files/";
		
	}

	public function transform (){
		global $BASE_URI,$DF_URI,$HOST;
		
		$this->foFile = "{$this->layout}.{$this->layoutExt}";
		$this->xsl = new DomDocument ("1.0","UTF-8");
		$this->xp = new XsltProcessor ();
		$this->xsl->load (stripslashes("{$this->xslDir}{$this->foFile}"));
		$this->xp->importStylesheet($this->xsl);
		$myDom=new DOMDocument("1.0","UTF-8");
		$parteDati=new DOMDocument("1.0","UTF-8");
		$tipoDiDati=$this->typeElement($this->dom);

		$risPart=$parteDati->createElement("dati");
		$risPart=$parteDati->appendChild($risPart);
		if($tipoDiDati!=false){
			$dati=$this->dom->getElementsByTagName($tipoDiDati);
			$nodoDati=$parteDati->importNode($dati->item(0),true);
			$risPart->appendChild($nodoDati);
			if($tipoDiDati!="speciali"){
				$speciali=$this->dom->getElementsByTagName("speciali");
				if($speciali->length!=0){
					$nodoSpeciali=$parteDati->importNode($speciali->item(0),true);
					$risPart->appendChild($nodoSpeciali);
				}
				
			}
		}
		$myDom->load(stripslashes("{$this->xslDir}{$this->skin}.xsl"));

		
		$this->xp->setParameter ('', "layout", "struttura.xsl");
		$this->xp->setParameter ('', "template", "template.xsl");
		$ris=$this->xp->transformToDoc($myDom);
		$beta="zio";
		write_xml_file ($ris, "{$this->xslDir}{$beta}.xsl");
		$digest=sha1($ris->saveXML().$_SERVER["REMOTE_ADDR"].gettimeofday(true));
		write_xml_file ($parteDati, $this->tempDir.$digest.".xml");
		exec("fop-0.94/fop -xml {$this->tempDir}{$digest}.xml -xsl {$this->xslDir}{$beta}.xsl -pdf {$this->pdfDir}{$tipoDiDati}-{$digest}.pdf");
		unlink($this->tempDir.$digest.".xml");
		unlink("{$this->xslDir}{$beta}.xsl");
		echo "http://{$HOST}{$DF_URI}/pdf/files/{$tipoDiDati}-{$digest}.pdf";

	}
	
	/*
	 * Vado a controllare e a ritornare il tipo di documento passato
	 * Prima controlla se e' response,scheda,errore
	 * Poi verifica se si tratta di speciali oppure non e' nessuno dei precedenti
	 */
	public function typeElement($dom2process){
			$possibility = array("scheda","response","errore");
			$i;
			for($i=0;$i<count($possibility);$i++){
				$content=$dom2process->getElementsByTagName($possibility[$i]);
				if($content->length!=0){return $possibility[$i];}
			}
			$content=$dom2process->getElementsByTagName("speciali");
			if($content->length!=0){return "speciali";}
			else{return false;}
	}		
	
	/*
	 * Cerchiamo un file xsl di percorso layoutDir/layout-skin.xsl
	 */
	public function layoutAndSkinExist ()
	{	
		if (!file_exists ("{$this->layoutDir}/{$this->layout}.{$this->layoutExt}")) {
			echo DFError ("404", "Layout {$this->layout} inesistente.");
			return false;
		}

		if ($this->skin != ""
		    && !file_exists ("{$this->skinDir}/{$this->skin}.{$this->skinExt}")) {
			echo DFError ("404", "Skin {$this->skin} inesistente.");
			return false;
		}
		return true;
	}
}


class ASCIIDocumentFormatter extends AbstractFormatter
{
	protected $xp;
	protected $xsl;

	public function __construct ()
	{
		parent::__construct ();

		$this->name = "borlengo";
		$this->xsl = new DomDocument ("1.0","UTF-8");
		$this->xp = new XsltProcessor ();
		$this->xsl->load ("{$this->xslDir}/borlengo.xsl");
		$this->xp->importStylesheet ($this->xsl);
	}

	public function layoutAndSkinExist ()
	{
		return true;
	}

	public function transform ()
	{
		if ($text = $this->xp->transformToXML($this->dom)) {
			output_typed_string ($text, "text/plain");
			return true;
		}
	}
}

?>
